using System;
using System.Collections.Generic;
using System.Text;

namespace Common.Utilities
{
    /// <summary>
    /// 
    /// </summary>
    public class StatsUtil
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="inputs"></param>
        /// <returns></returns>
        public static float GetAverage(List<float> inputs)
        {
            if(inputs !=null && inputs.Count>0)
            {
                float sum = 0f;
                foreach(float input in inputs)
                {
                    sum += input;
                }
                return sum/inputs.Count;
            }
            else
            {
                throw new Exception("Input is empty");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="inputs"></param>
        /// <returns></returns>
        public static double? GetAverage(List<double> inputs)
        {
            if (inputs != null && inputs.Count > 0)
            {
                double sum = 0f;
                foreach (double input in inputs)
                {
                    sum += input;
                }
                return sum / inputs.Count;
            }
            else
            {
                return null;
            }
        }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="distances"></param>
		/// <returns></returns>
    	public static double GetMedian(List<double> distances)
    	{
			if (distances == null || distances.Count == 0)
				return 0;

    		distances.Sort();
			if (distances.Count % 2 == 0)
				return distances[distances.Count / 2];
			else
				return distances[(distances.Count - 1)/2];
    	}

		/// <summary>
		/// 10% of value (0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0) returns 0.1, 
		/// while 100% yields 1.0 (Highest value)
		/// </summary>
		/// <param name="values"></param>
		/// <param name="lowPercent"></param>
		/// <returns></returns>
    	public static double? GetLowPercentile(List<double> values, int lowPercent)
    	{
			if (values == null || values.Count == 0)
				return null;

    		values.Sort();
		    int idx = (int) (values.Count*((double) lowPercent/100));
			if (values.Count > idx)
				return values[idx];
			else if (values.Count == idx)
				return values[idx - 1];
			else
				return values[values.Count - 1];
    	}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static double? GetMax(List<double> values)
        {
            if (values != null && values.Count > 0)
            {
                values.Sort();
                return values[values.Count - 1];
            }
            else
                return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static double? GetMin(List<double> values)
        {
            if (values != null && values.Count > 0)
            {
                values.Sort();
                return values[0];
            }
            else
                return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static double? GetStandardDeviation(List<double> values)
        {
            if (values != null && values.Count > 0)
            {
                double avg = StatsUtil.GetAverage(values).Value;
                double sum = 0;
                foreach(double v in values)
                {
                    sum += Math.Pow(v - avg, 2);
                }
                return Math.Sqrt(sum/values.Count);
            }
            else
                return null;
        }
    }
}
